﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace IFT.Classes
{
  [XmlRoot("unitSetup")]
  public class UnitManager
  {
    #region Singleton
    // Creating a single static instance of the class
    // this is not thread safe, will be added later
    private static volatile UnitManager m_singleton;
    private static object baseProc = new Object();
    // Retrieve or Set the static Instance
    public static UnitManager Instance
    {
      get
      {
        if (m_singleton == null)
        {
          //lock Thread for other processes and start loading
          lock (baseProc)
            m_singleton = UnitManager.LoadUnits();
        }

        return m_singleton;
      }
      set { m_singleton = value; }
    }
    #endregion
    private ArrayList listUnits;

    public UnitManager()
    {
      listUnits = new ArrayList();
    }

    [XmlElement("unit")]
    public XMLUnit[] Units
    {
      get
      {
        XMLUnit[] units = new XMLUnit[listUnits.Count];
        listUnits.CopyTo(units);
        return units;
      }
      set
      {
        if (value != null)
        {
          listUnits.Clear();
          XMLUnit[] unitList = (XMLUnit[])value;

          foreach (XMLUnit unit in unitList)
            AddUnit(unit);
        }
      }
    }

    public XMLUnit GetUnit(int unitId)
    {
      if (unitId > listUnits.Count || unitId < 0)
        return null;

      return (XMLUnit)listUnits[unitId - 1];
    }

    public bool UnitExists(int unitId)
    {
      return GetUnit(unitId) != null;
    }

    public static UnitManager LoadUnits()
    {
      UnitManager newManager = new UnitManager();
      XmlSerializer xmlserial = new XmlSerializer(typeof(UnitManager));
      TextReader txtreader = new StreamReader(System.Windows.Forms.Application.StartupPath + "\\config\\UnitConfig.xml");
      newManager = (UnitManager)xmlserial.Deserialize(txtreader);
      txtreader.Close();
      return newManager;
    }

    public void SaveRules()
    {
      XmlTextWriter txtWriter = new XmlTextWriter(System.Windows.Forms.Application.StartupPath + "\\config\\UnitConfig.xml", Encoding.UTF8);
      txtWriter.Formatting = Formatting.Indented;

      txtWriter.WriteStartDocument();
      txtWriter.WriteStartElement("unitSetup");
      txtWriter.WriteAttributeString("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
      txtWriter.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");

      foreach (XMLUnit unit in listUnits)
      {
        txtWriter.WriteStartElement("unit");
        txtWriter.WriteAttributeString("name", unit.Name);
        {
          txtWriter.WriteStartElement("stats");
          txtWriter.WriteAttributeString("Hitpoints", Convert.ToString(unit.Stats.Hitpoints));
          txtWriter.WriteAttributeString("Armour", Convert.ToString(unit.Stats.Armour));
          txtWriter.WriteAttributeString("Speed", Convert.ToString(unit.Stats.Speed));
          txtWriter.WriteAttributeString("Size", Convert.ToString(unit.Stats.Size));
          txtWriter.WriteAttributeString("Damage", Convert.ToString(unit.Stats.Damage));
          txtWriter.WriteAttributeString("CargoSpace", Convert.ToString(unit.Stats.CargoSpace));
          txtWriter.WriteAttributeString("Level", Convert.ToString(unit.Stats.Level));
          txtWriter.WriteAttributeString("BuildTime", Convert.ToString(unit.Stats.BuildTime));
          txtWriter.WriteAttributeString("BarrackLevel", Convert.ToString(unit.Stats.BarrackLevel));
          txtWriter.WriteAttributeString("UnitType", Convert.ToString(unit.Stats.UType));
          txtWriter.WriteAttributeString("Accuracy", Convert.ToString(unit.Stats.Accuracy));
          txtWriter.WriteEndElement();

          txtWriter.WriteStartElement("cost");
          txtWriter.WriteAttributeString("Wood", Convert.ToString(unit.Cost.Wood));
          txtWriter.WriteAttributeString("Sulphur", Convert.ToString(unit.Cost.Sulphur));
          txtWriter.WriteAttributeString("Wine", Convert.ToString(unit.Cost.Wine));
          txtWriter.WriteAttributeString("Crystal", Convert.ToString(unit.Cost.Crystal));
          txtWriter.WriteAttributeString("Citizen", Convert.ToString(unit.Cost.Citizen));
          txtWriter.WriteAttributeString("Upkeep", Convert.ToString(unit.Cost.Upkeep));
          txtWriter.WriteEndElement();
        }
        txtWriter.WriteEndElement();
      }

      txtWriter.WriteEndElement();
      txtWriter.WriteEndDocument();
      txtWriter.Close();
    }

    public void AddUnit(XMLUnit newUnit)
    {
      if (newUnit != null)
      {
        newUnit.ID = listUnits.Count + 1;
        listUnits.Add(newUnit);
      }
    }
  }

  public class XMLUnit
  {
    private int m_id;
    private UnitStats m_stats;
    private UnitCost m_cost;

    [XmlAttribute("Name")]
    public string Name;

    [XmlElement("stats")]
    public UnitStats Stats
    {
      get { return m_stats; }
      set
      {
        if (value != null)
          m_stats = (UnitStats)value;
      }
    }

    [XmlElement("cost")]
    public UnitCost Cost
    {
      get { return m_cost; }
      set
      {
        if (value != null)
          m_cost = (UnitCost)value;
      }
    }

    public int ID
    {
      get { return m_id; }
      set { m_id = (int)value; }
    }

    public UnitType Type
    {
      get { return (m_stats == null) ? UnitType.MinUnitFieldType : (UnitType)m_stats.UType; }
    }

    public XMLUnit()
    {
      m_stats = new UnitStats();
      m_cost = new UnitCost();
    }
  }

  public class UnitStats
  {
    [XmlAttribute(DataType = "int", AttributeName = "Hitpoints")]
    public int Hitpoints;
    [XmlAttribute(DataType = "int", AttributeName = "Armour")]
    public int Armour;
    [XmlAttribute(DataType = "int", AttributeName = "Speed")]
    public int Speed;
    [XmlAttribute(DataType = "int", AttributeName = "Size")]
    public int Size;
    [XmlAttribute(DataType = "int", AttributeName = "Damage")]
    public int Damage;
    [XmlAttribute(DataType = "int", AttributeName = "CargoSpace")]
    public int CargoSpace;
    [XmlAttribute(DataType = "int", AttributeName = "Level")]
    public int Level;
    [XmlAttribute(DataType = "int", AttributeName = "BuildTime")]
    public int BuildTime;
    [XmlAttribute(DataType = "int", AttributeName = "BarrackLevel")]
    public int BarrackLevel;
    [XmlAttribute(DataType = "int", AttributeName = "UnitType")]
    public int UType;
    [XmlAttribute(DataType = "int", AttributeName = "Accuracy")]
    public int Accuracy;

    public UnitStats() { }
  }

  public class UnitCost
  {
    [XmlAttribute(DataType = "int", AttributeName = "Wood")]
    public int Wood;
    [XmlAttribute(DataType = "int", AttributeName = "Sulphur")]
    public int Sulphur;
    [XmlAttribute(DataType = "int", AttributeName = "Wine")]
    public int Wine;
    [XmlAttribute(DataType = "int", AttributeName = "Crystal")]
    public int Crystal;
    [XmlAttribute(DataType = "int", AttributeName = "Citizen")]
    public int Citizen;
    [XmlAttribute(DataType = "int", AttributeName = "Upkeep")]
    public int Upkeep;

    public UnitCost() { }
  }
}

